/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package carreras.entidades;

import carreras.logger.CarrerasLogger;
import carreras.negocio.NegCompetencia;
import carreras.negocio.NegInscripcion;
import carreras.negocio.NegTorneo;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Comparator;


/**
 *
 * @author Fanky10 <fanky10@gmail.com>
 */
public class ManagerTorneo {
    private Torneo torneo;
    private Competencia competencia_actual;
    /**
     * 
     * @throws SQLException si no se pudo guardar el torneo o la competencia
     */
    private ManagerTorneo() throws SQLException{
        init();
        
    }
    /**
     * creo en la base de datos el nuevo torneo y la competencia inicial
     * @throws SQLException si no se pudo guardar el torneo o la competencia
     */
    private void init() throws SQLException{        
        torneo = new NegTorneo().nuevoTorneo();
        nueva_competencia(Competencia.COMPETENCIA_LIBRE);
    }
    private static ManagerTorneo singleton;
    public static ManagerTorneo getInstance(){
        if(singleton==null){
            createInstance();
        }
        return singleton;
    }
    private static void createInstance(){
        try{
            singleton = new ManagerTorneo();
        }catch(SQLException ex){
            System.err.println("No se pudo crear el manager de torneo: "+ex.getLocalizedMessage());
            System.exit(0);
        }
    }
    /**
     * genera una competencia segun una logica interna.
     * @throws SQLException si no se pudo guardar la misma
     */
    public void nueva_competencia() throws SQLException{
        if(competencia_actual.getTipo_competicion() == Competencia.COMPETENCIA_LIBRE){
            nueva_competencia(Competencia.COMPETENCIA_PRELIMINAR);
        }else if(competencia_actual.getTipo_competicion() == Competencia.COMPETENCIA_PRELIMINAR){
            nueva_competencia(Competencia.COMPETENCIA_ELIMINATORIA);
        }else{
            throw new IllegalArgumentException("No soporto mas competencias!!");
        }
    }
    public void fin_inscripcion() throws SQLException{
        //a la actual la limpio y le pongo los nuevos inscriptos con sus corresp. categ
        competencia_actual.clear();
        CatCorredorAuto inscriptos = new NegInscripcion().getInscriptos(torneo); 
        CarrerasLogger.debug(ManagerTorneo.class,"inscriptos.size() "+inscriptos.size());
        competencia_actual.addAll(inscriptos);
        CarrerasLogger.debug(ManagerTorneo.class,"competencia_actual.size() "+competencia_actual.size());
        //luego llamo a una nueva competencia!
        nueva_competencia();
        //FIXME: que onda con esto..? agrega como tiene que ser?!
        CarrerasLogger.debug(ManagerTorneo.class,"competencia_actual.size() after new "+competencia_actual.size());
    }
    /**
     * genera una nueva competencia 
     * @param tipo el tipo de la competencia
     * @throws SQLException si no se pudo guardar la misma
     */
    private void nueva_competencia(int tipo) throws SQLException{
        nueva_competencia(tipo, Competencia.NUMERO_RONDA_INICIAL);
    }
    /**
     * genera una nueva competencia con los parametros dados
     * @param tipo tipo de la competencia
     * @param nro_ronda el numero de ronda de la misma
     * @throws SQLException si no se pudo guardar la misma
     */
    private void nueva_competencia(int tipo,int nro_ronda) throws SQLException{
        
//        this.competencia_actual = new Competencia(tipo, nro_ronda);
//        competencia_actual.setId(new NegCompetencia().nuevaCompetencia(torneo.getId(), competencia_actual));
//        torneo.add(competencia_actual);
        competencia_actual = genera_nueva_competencia(tipo, nro_ronda);
        torneo.add(competencia_actual);
    }
    private Competencia genera_nueva_competencia(int tipo, int nro_ronda) throws SQLException{
        Competencia c = new Competencia(tipo, nro_ronda);
        c.setId(new NegCompetencia().nuevaCompetencia(torneo.getId(), c));
        if(competencia_actual!=null){
            
            //las filtro --> pidiendole a c/una que elimine a su bicho
            //les pido el arreglo de bichos (CorredorAuto)
            for(Carrera ci: competencia_actual){
                ci.eliminaPerdedor();
            }
            //lo agrego a esta nueva competencia
            final CatCorredorAuto corredores = competencia_actual.getCorredoresAutosActivos();
            //shufleo la competencia y luego los ordeno
            Collections.shuffle(corredores);
            //consigo un grupo de carreras por categoria, 
            //las ordeno por categoria --mejor
            //y luego por estado comp.
            Collections.sort(corredores, new Comparator<CorredorAuto>(){

                @Override
                public int compare(CorredorAuto c1, CorredorAuto c2) {
                    //sin el getestadocomp andaba bien hey! xD
                    Integer cat1 = c1.getCategoria().getId();
                    Integer cat2 = c2.getCategoria().getId();
                    int catComp = cat1.compareTo(cat2);
                    if(catComp!=0){
                        return catComp;
                    }else{
                        Integer ecomp1 = c1.getEstado_competencia();
                        Integer ecomp2 = c2.getEstado_competencia();
                        return ecomp1.compareTo(ecomp2);
                    }
//                    if(c1.getCategoria().getId()>c2.getCategoria().getId()){
//                        return -1;
//                    }else if(c1.getCategoria().getId()<c2.getCategoria().getId()){
//                        return 1;
//                    }else{
//                        if(c1.getEstado_competencia()>c2.getEstado_competencia()){
//                            return -1;
//                        }else if(c1.getEstado_competencia()<c2.getEstado_competencia()){
//                            return 1;
//                        }else{
//                            return 0;
//                        }
//                    }
//                    if(c1.getCategoria().getId()>c2.getCategoria().getId() && c1.getEstado_competencia()>c2.getEstado_competencia()){
//                        return -1;
//                    }else if(c1.getCategoria().getId()<c2.getCategoria().getId() && c1.getEstado_competencia()<c2.getEstado_competencia()){
//                        return 1;
//                    }else{
//                        return 0;
//                    }
                }

            });
            
            //consigo los ganadores de cat.
            CatCorredorAuto catwinV = corredores.getGanadoresCat();
            //no hago nada por ahora :P
            
            //reinicio los jugadores :D
            for(CorredorAuto ca: corredores){
                ca.setEsta_actualizado(false);
                ca.setEstado_carrera(CarrilCarrera.ESTADO_SIN_DATOS);
            }
            c.addAll(corredores);
            //esto en la v1.4.5 andaba.. cualquier cosa rollbackear :P
//            for(CorredorAuto ca: corredores){
//                ca.setEsta_actualizado(false);
//                ca.setEstado_carrera(CarrilCarrera.ESTADO_SIN_DATOS);
//                c.add(ca);
//            }
        }
        
        //la devuelvo (:
        return c;
    }
    /**
     * genera una nueva ronda, con la competencia actual
     * @throws SQLException si no puede guardarse la competencia
     */
    public void nueva_ronda() throws SQLException{
        //CASO ESPECIAL competencia preliminar tiene solo UNA RONDA
        //TODO: si termina la preliminar hay que actualizar los estados internos de los bichos!
        if(competencia_actual.getTipo_competicion() == Competencia.COMPETENCIA_PRELIMINAR){
            competencia_actual.fin_competencia_preeliminar();
            nueva_competencia();
            return;
        }
//        final CatCorredorAuto corredores = competencia_actual.getCorredoresAutosActivos();
        int nueva_ronda = competencia_actual.getNumero_ronda() + 1;
        int tipo_competencia_actual = competencia_actual.getTipo_competicion();
        nueva_competencia(tipo_competencia_actual, nueva_ronda);
//        nueva_competencia(tipo_competencia_actual, nueva_ronda);
//        for(CorredorAuto ca: corredores){
//            ca.setEsta_actualizado(false);
//            ca.setEstado_carrera(CarrilCarrera.ESTADO_SIN_DATOS);
//            competencia_actual.add(ca);
//        }
//        //por ultimo reordenamos la lista de corredores para que no corran igual
//        reordena_corredores();
    }
    /**
     * por si se quiere implementar algo mas loco, 
     * aqui es donde se tiene que toquetear
     */
//    private void reordena_corredores(){
//        Collections.shuffle(competencia_actual);
//    }
    /**
     * 
     * @return devuelve la competencia en uso
     */
    public Competencia getCompetencia_actual() {
        return competencia_actual;
    }
    
    public Torneo getTorneo(){
        return torneo;
    }
    
    
}
